#include "embeddedinput.h"
#include <QFile>
#include <QDebug>
#include "mylogger.h"

#ifdef Q_OS_LINUX
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <linux/input.h>
#include <string.h>
#include <errno.h>
#endif

using namespace ns_yht;

EmbeddedInput::EmbeddedInput(QObject *parent)
    : QObject(parent)
{
}

EmbeddedInput::~EmbeddedInput()
{
#ifdef Q_OS_LINUX
    // 清理所有打开的设备
    for (const auto &device : m_inputDevices)
    {
        if (device.notifier)
        {
            device.notifier->setEnabled(false);
            delete device.notifier;
        }
        if (device.fd >= 0)
        {
            close(device.fd);
        }
    }
#endif
}

bool EmbeddedInput::addInputDevice(const QString &devicePath)
{
#ifndef Q_OS_LINUX
    Q_UNUSED(devicePath);
    return false;
#else
    // 检查设备文件是否存在
    if (!QFile::exists(devicePath))
    {
        if (GLOG)
        {
            GLOG->info("Input device {} does not exist", devicePath.toStdString());
        }
        return false;
    }

    // 以只读和非阻塞方式打开设备
    int fd = open(devicePath.toLocal8Bit().constData(), O_RDONLY | O_NONBLOCK);
    if (fd < 0)
    {
        if (GLOG)
        {
            GLOG->info("Failed to open input device {}: {}",
                       devicePath.toStdString(), strerror(errno));
        }
        return false;
    }

    // 检查是否为input设备
    char name[256] = {0};
    if (ioctl(fd, EVIOCGNAME(sizeof(name) - 1), name) < 0)
    {
        if (GLOG)
        {
            GLOG->info("Device {} is not an input event device",
                       devicePath.toStdString());
        }
        close(fd);
        return false;
    }

    // 创建QSocketNotifier来监视设备文件描述符
    auto *notifier = new QSocketNotifier(fd, QSocketNotifier::Read, this);

    // 连接信号槽
    connect(notifier, &QSocketNotifier::activated,
            this, [this, fd](int socket)
            {
        Q_UNUSED(socket);
        handleInputEvent(fd); });

    // 保存设备信息
    InputDevice device;
    device.fd = fd;
    device.notifier = notifier;
    m_inputDevices.append(device);

    if (GLOG)
    {
        GLOG->info("Successfully added input device {}: {}",
                   devicePath.toStdString(), name);
    }

    return true;
#endif
}

void EmbeddedInput::handleInputEvent(int socket)
{
#ifndef Q_OS_LINUX
    Q_UNUSED(socket);
#else
    struct input_event event;
    ssize_t n;

    // 读取所有可用的事件
    while ((n = read(socket, &event, sizeof(event))) > 0)
    {
        if (n != sizeof(event))
        {
            if (GLOG)
            {
                GLOG->info("Incomplete event read from input device: {}", n);
            }
            continue;
        }

        // 只处理按键事件
        if (event.type == EV_KEY)
        {
            switch (event.value)
            {
            case 0: // 按键释放
                emit keyReleased(event.code);
                if (GLOG)
                {
                    GLOG->info("Key released: {}", event.code);
                }
                break;
            case 1: // 按键按下
                emit keyPressed(event.code);
                if (GLOG)
                {
                    GLOG->info("Key pressed: {}", event.code);
                }
                break;
            case 2: // 按键重复（自动重复）
                // 可以根据需要处理自动重复事件
                if (GLOG)
                {
                    GLOG->info("Key repeat: {}", event.code);
                }
                break;
            }
        }
    }

    // 检查是否出错
    if (n < 0 && errno != EAGAIN)
    {
        if (GLOG)
        {
            GLOG->info("Error reading from input device: {}", strerror(errno));
        }
    }
#endif
}